Centralt innehåll

1. Klasser & Objekt

Var inte orolig om du blir förvirrad av det här kapitlet. Klasser och objekt kan ta ett tag att förstå, men ofta blir det hela tydligt efter att man börjar skriva egna program som använder sig av det.

1.1 Procedurell programmering

Programmering handlar om att lösa problem. För att göra det har vi hittills mesta använt oss av procedurell programmering. Där försöker vi lösa ett visst problem genom att anropa funktioner.

1.2 Objektorienterad Programmering (OOP)

Programmering handlar också om att försöka få programmet så överskådligt och lättbegripligt som möjligt. Objektorienterad programmering (OOP) används för att modellera saker från den verkliga världen i kod. Det finns flera fördelar med det objektorienterade angreppssättet, koden blir bl.a enklare att underhålla (utöka, ändra, felsöka). De fördelarna uppnås framförallt i större projekt.

Objektorienterad programmering (OOP) är ett modernare sätt att skriva kod. OOP baseras på idén att gruppera egenskaper (attribut) och beteenden (metoder) till enheter av information, som kallas objekt.

2. Klasser

Klasser är väldigt användbart i programmering. Du använder dem hela tiden, utan att tänka på det. Vi har faktiskt redan använt några typer av klasser, t.ex. listor. Klasserna för listor är inbyggda i Python, och det finns massor av inbyggda klasser i Python man kan använda.

Klassen är mallen som används för att skapa ett verkligt objekt, t.ex. en lista med olika element (värden). En lista har ju värden och metoder kopplade till sig.

2.1 Egna klasser

Klasserna för listor är inbyggda i Python, och det finns massor av inbyggda klasser man kan använda. Men nu ska vise hur man kan bygga sin egen klass med attribut och metoder.

Om man t.ex. ska skapa ett program som hanterar punkter i ett koordinatsystem och dess egenskaper som x, y värden är det bra att hålla ihop punktens värden. Då är det lämpligt att använda en klass.

En klass i Python skapas genom att använda nyckelordet class och ge det ett namn, som i det här exemplet:

class Punkt:
    def __init__(self, x, y):
        self.x = x
        self.y = y
	
start_punkt = Punkt(3, -3)  # Skapa ett objekt från klassen Punkt

print(f'Startpunkten har koordinaten {start_punkt.x}, {start_punkt.y}')
ger utskriften
Startpunkten har koordinaten 3, -3
Klassens namn skapas efter samma regler och med samma begränsningar som variabelnamn. Praxis är att klassnamnet ska inledas med versal (stor bokstav) och vara singularis (ental).

Nyckelordet self referar till objektet självt. Koden self.x innebär att attributet kopplas till objektet.

Uttrycket start_punkt.x betyder "gå till objektet start_punkt och hämta värdet för attributet x".

2.2 Klasser vs Objekt

3. Konstruktor

För att kunna skapa mer flexibla klasser används något som kallas konstruktor. Konstruktorn används när objekt från en klass skapas. Det är här man ger objektet de värden som man önskar att objektet ska ha.

Konstruktorn är en särskild funktion som bara anropas när objektet skapas. Konstruktorn anropas endast en gång. I Python har konstruktorn namnet __init__. Du måste också definiera ett särskilt nyckelord, self, som en parameter till konstruktorn.

class Punkt:
    def __init__(self, x, y):  # The constructor
        self.x = x  # Attribute
        self.y = y  # Attribute
        
# Create objects from the class Punkt
start_punkt = Punkt(3, -3)  # self is not given as an argument
slut_punkt = Punkt(4, 4)

print(f'Startpunkten har koordinaten {start_punkt.x}, {start_punkt.y}')
print(f'Slutpunkten har koordinaten {slut_punkt.x}, {slut_punkt.y}')
ger utskriften
Startpunkten har koordinaten (3, -3)
Slutpunkten har koordinaten (4, 4)

3.1 self

Nyckelordet self refererar (pekar) till sig själv. Alla tilldelningar med nyckelordet self innebär att variabeln tillhör objektet.
Om man inte lägger till self kommer det i stället att behandlas som en lokal variabel, som ju är tillfällig, och som inte finns kvar efter att metoden __init()__ har körts.

För att visa hur self fungerar kan du tänka på följande kod där tre variabler x, y och z, tilldelas i __init__().

class Punkt:
  def __init__(self, a, b, c):
    self.x = a  # Attributet hör till objektet
    self.y = b  # Attributet hör till objektet
    z = c       # En lokal variabel i konstruktorn
	
start_punkt = Punkt(3, 3, 1)
print(start_punkt.x) 
print(start_punkt.y) 
print(start_punkt.z)  # Error, för att z tillhör inte objektet
ger utskriften
3
3Traceback (most recent call last):
  File "main.py", line 10, in 
    print(start_punkt.z)  # Error, because z does not belong to the object
AttributeError: 'Punkt' object has no attribute 'z'

4. Metoder

Förutom egenskaper (attribut) kan klasser även ha beteende (metoder).

Många säger funktioner om metoder och tvärtom, vilket är ok och inte konstigt eftersom de är samma sak, men i lite olika sammanhang. Metoder är ju funktioner som är kopplade till objekt och man behöver ett objekt för att anropa metoderna.

class Punkt:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def distans_från_origo(self):	
        avstånd = ((self.x ** 2) + (self.y ** 2)) ** 0.5  # Pythagoras sats, upphöjt till 0.5 är samma som kvadroten
        return avstånd

start_punkt = Punkt(3, 4)  # Skapa ett objekt
avstånd = start_punkt.distans_från_origo()  # Anropa objektets metod
print(avstånd)
ger utskriften
5.0

Vad blir utskriften med följande kod?

class Punkt:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def distans_från_origo(self):	
        avstånd = ((self.x ** 2) + (self.y ** 2)) ** 0.5  # Pythagoras sats, upphöjt till 0.5 är samma som kvadroten
        return avstånd

start_punkt = Punkt(3, 4)  # Skapa ett objekt
print(start_punkt)
ger utskriften
<__main__.Punkt object at 0x7f3298b71fa0>
Det är minnesadressen till objektet som skrivs ut, dvs var i minnet objektet lagras. Körs koden flera gånger blir minnesadresserna olika.

Det finns en speciell metod __str__ som kan användas för att få en bättre utskrift än själva minnesadressen. Den metoden anropas varje gång objektet försöker omvandla datatypen till en sträng, t.ex. när satsen print(start_punkt) körs. Metoden returnerar då en sträng, som i det här fallet används vid utskrift.

class Punkt:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        str = f'({self.x}, {self.y})'
        return str

    def distans_från_origo(self):	
        avstånd = ((self.x ** 2) + (self.y ** 2)) ** 0.5  # Pythagoras sats, upphöjt till 0.5 är samma som kvadroten
        return avstånd

start_punkt = Punkt(3, 4)  # Skapa ett objekt
print(start_punkt)
ger utskriften
(3, 4)

Metoder i klasser ska inte ha några egna utskrifter utan returnera värden. Klasserna blir då mer generella och flexibla och kan återanvändas i flera olika projekt och program. Helt enkelt god design att göra på detta sätt.

Att många exempel och videos har utskrifter i metoder är för att visa hur olika koncept fungerar. I ett verkligt projekt ska utskrifter undvikas från generella klasser. Speciella klasser som hanterar användrargränsnittet hanterar utskrifter.

Begrepp

Procedurell programmering: Lösa problem genom att anropa funktioner.

Objektorienterad programmering: Lösa problem genom att gruppera attribut och metoder i objekt.

Klass: En mall för att skapa objekt.

Objekt: En verklig förekomst av en klass.

Instans: Ett annat ord för objekt.

Instansiera: Skapa ett objekt.

Attribut: Variabler i en klass.

Metod: En funktion kopplad till ett objekt.

Konstruktor: En metod som automatiskt anropas när ett objekt skapas.

Fakta

Övningar

Inlämningsuppgift

login     logout    

Exit tickets